/*
 * Copyright (C) 2010-2011 Comcast Cable.  All Rights Reserved.
 */
package com.hercules.android.receiver.handlers.commands;

import com.hercules.android.receiver.AndroidReceiver;
import com.hercules.android.receiver.LogUtil;
import com.hercules.android.receiver.model.commands.XRECommand;

import java.util.logging.Logger;

/**
 * This class declares the method that will be called by the {@link XREAggregateCommandHandler}. It also has pre / post
 * command message handlers of XREAuxiliaryCommandHandler type that are called by the handler before / after processing
 * the actual command message. The actual handler functionality is in processCommandMessage() method which is
 * abstracted, to be implemented by the subclasses.
 * <p>
 * <b>Thread Safety:</b> This class is not thread safe since it has mutable fields. But if they are not changed after
 * first configured, then this class is used in a thread safe manner.
 *
 * @author liuliquan, 7realm
 * @version 1.0
 */
public abstract class XRECommandHandler {
    /**
     * The auxiliary handler called before processing the actual command message.
     * <p>
     * Initial value is null. Can be any value. If it is null then no pre processing will be performed. It has getter
     * and setter.
     */
    private AuxiliaryXRECommandHandler preCommandMessageHandler;

    /**
     * The auxiliary handler called after processing the actual command message.
     * <p>
     * Initial value is null. Can be any value. If it is null then no post processing will be performed. It has getter
     * and setter.
     */
    private AuxiliaryXRECommandHandler postCommandMessageHandler;

    /**
     * The logger used to perform logging.
     * <p>
     * Initial value is null. Can be any value. If it is null then no logging will be performed. It has getter and
     * setter.
     */
    private Logger logger = LogUtil.getLogger(getClass().getSimpleName());

    /**
     * Default empty constructor.
     */
    protected XRECommandHandler() {
        // empty
    }

    /**
     * Handle given command message.
     *
     * @param command the XRE command to be handled
     * @param receiver the receiver for the XRE application
     * @throws IllegalArgumentException if given command or receiver is null
     * @throws XRECommandHandlerException if any error occurs while handling the command
     */
    public void onCommandMessage(XRECommand command, AndroidReceiver receiver) throws XRECommandHandlerException {
        String methodName = "onCommandMessage";
        LogUtil.enter(logger, this, methodName, command, receiver);

        // arguments will be checked in actual handlers
        try {
            // pre process command
            if (preCommandMessageHandler != null) {
                preCommandMessageHandler.processCommandMessage(command, receiver);
            }

            // actually process command
            processCommandMessage(command, receiver);

            // post process command
            if (postCommandMessageHandler != null) {
                postCommandMessageHandler.processCommandMessage(command, receiver);
            }
            LogUtil.exit(logger, this, methodName);
        } catch (IllegalArgumentException e) {
            throw LogUtil.error(logger, this, methodName, e);
        } catch (XRECommandHandlerException e) {
            throw LogUtil.error(logger, this, methodName, e);
        }
    }

    /**
     * The abstract method to be implemented by subclasses to actually process the command message.
     *
     * @param command the XRE command to be handled
     * @param receiver the receiver for the XRE application
     * @throws IllegalArgumentException if given command or receiver is null
     * @throws XRECommandHandlerException if any error occurs while handling the command
     */
    protected abstract void processCommandMessage(XRECommand command, AndroidReceiver receiver)
        throws XRECommandHandlerException;

    /**
     * Gets the auxiliary handler called before processing the actual command message.
     *
     * @return the auxiliary handler called before processing the actual command message
     */
    public AuxiliaryXRECommandHandler getPreCommandMessageHandler() {
        return preCommandMessageHandler;
    }

    /**
     * Sets the auxiliary handler called before processing the actual command message.
     *
     * @param preCommandMessageHandler the auxiliary handler called before processing the actual command message
     */
    public void setPreCommandMessageHandler(AuxiliaryXRECommandHandler preCommandMessageHandler) {
        this.preCommandMessageHandler = preCommandMessageHandler;
    }

    /**
     * Gets the auxiliary handler called after processing the actual command message.
     *
     * @return the auxiliary handler called after processing the actual command message
     */
    public AuxiliaryXRECommandHandler getPostCommandMessageHandler() {
        return postCommandMessageHandler;
    }

    /**
     * Sets the auxiliary handler called after processing the actual command message.
     *
     * @param postCommandMessageHandler the auxiliary handler called after processing the actual command message
     */
    public void setPostCommandMessageHandler(AuxiliaryXRECommandHandler postCommandMessageHandler) {
        this.postCommandMessageHandler = postCommandMessageHandler;
    }

    /**
     * Gets the logger used to perform logging.
     *
     * @return the logger used to perform logging
     */
    public Logger getLogger() {
        return logger;
    }

    /**
     * Sets the logger used to perform logging.
     *
     * @param logger the logger used to perform logging
     */
    public void setLogger(Logger logger) {
        this.logger = logger;
    }
}